home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr43 / ppl4p10.zip / ZMODEM.PAS < prev   
Pascal/Delphi Source File  |  1995-02-20  |  45KB  |  1,956 lines

  1. (*
  2. **
  3. **   --- please read this ! ---
  4. **
  5. **  This source code is in "shrouded" form. It is distributed in this form
  6. **  rather than as a library (.LIB) file because of the inconsistancies
  7. **  between object files generated by different compilers. To support several
  8. **  compilers would require a .LIB file for each compiler manufacturer, and
  9. **  sometimes several versions of the .LIB file are needed for the different
  10. **  versions of the same manufacturers compiler!
  11. **
  12. **  You can compile this code, but you will have to register with us in order
  13. **  to get the normal (commented) C source code with normal variable names.
  14. *)
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21.  
  22. UNIT zmodem;
  23.  
  24. INTERFACE
  25.  
  26. USES Crt, Dos, zdate, crc16, crc32, PCL4P, hex_io, term_io, file_io;
  27.  
  28. function ZmodemTx(
  29.          V70     : Integer;      { COM port }
  30.      Var V40 : String;       { file spec buffer }
  31.          V91   : Boolean)      { Can do streaming ? }
  32.        : Boolean;
  33.  
  34. function ZmodemRx(
  35.          V70     : Integer;      { COM port }
  36.      Var V39 : String;       { filename buffer }
  37.          V91   : Boolean)      { Can do streaming ? }
  38.        : Boolean;
  39.  
  40. IMPLEMENTATION
  41.  
  42. Const
  43.    Debug     = False;
  44.  
  45.    V117  = 1024;  {TX/RX buffer size}
  46.    V114  =   32;  {Attn buffer string size}
  47.  
  48.    V95 =    2;
  49.    V54  =    9;
  50.    V68   =   18;
  51.    V105  =   36;
  52.    V96  =  182;
  53.  
  54. Type
  55.    BufType  = BufferType;
  56.    HdrType  = Array[0..3] of Byte;
  57.  
  58. Const
  59.    V191  = 42;  { '*' }
  60.    V133  = 24;  { ^X  }
  61.    V134 = 88;
  62.    V115  = 65;  { 'A' }
  63.    V145  = 66;  { 'B' }
  64.    V116 = 67; { 'C' }
  65.  
  66.    V194 = 0;
  67.    V192  = 1;
  68.    V197  = 2;
  69.    V113    = 3;
  70.    V142   = 4;
  71.    V198   = 5;
  72.    V185    = 6;
  73.    V112  = 7;
  74.    V143    = 8;
  75.    V193   = 9;
  76.    V132   = 10;
  77.    V135    = 11;
  78.    V141   = 12;
  79.    V126    = 13;
  80.    V121 = 14;
  81.    V124   = 15;
  82.    V119     = 16;
  83.    V144 = 17;
  84.    V123 = 18;
  85.    V199  = 19;
  86.    V127 = 104; { 'h' }
  87.    V128 = 105; { 'i' }
  88.    V129 = 106; { 'j' }
  89.    V130 = 107; { 'k' }
  90.    V195 = 108; { 'l' }
  91.    V196 = 109; { 'm' }
  92.    V186 = 0;
  93.    V201 =  -1;
  94.    V136   = -40;
  95.    V72     = -41;
  96.    V53    = 256;
  97.    V49  = 360;
  98.    V50  = 361;
  99.    V51  = 362;
  100.    V52  = 363;
  101.    V48   = 272;
  102.  
  103.  Const
  104.    V28 = 5;
  105.    V10 = 24;
  106.    V110 = 19;
  107.    V111 = 17;
  108.    V87 = 1;
  109.    V93 = 2;
  110.    V30 = 4;
  111.    V1 = 6;
  112.    V63 = 21;
  113.    V18 = 26;
  114.    V34 = 27;
  115.  
  116. { byte positions }
  117. Const
  118.    V137 = 3;
  119.    V138 = 2;
  120.    V139 = 1;
  121.    V140 = 0;
  122.    V187 = 0;
  123.    V188 = 1;
  124.    V189 = 2;
  125.    V190 = 3;
  126.  
  127. { bit masks for V192 }
  128. Const
  129.    V15  =  1;    {handle full duplex  - YES}
  130.    V17 =  2;    {overlay disk and serial I/O - YES}
  131.    V11  =  4;    {send a break - YES}
  132.    V13  =  8;    {encrypt/decrypt - NO}
  133.    V16  = 16;    {LZW compress - NO}
  134.    V14 = 32;    {use 32 bit CRCs - YES}
  135.    V36  = 64;    {escapes all control chars - NO}
  136.    V35    =128;    {escapes the 8th bit - NO}
  137.  
  138. { bit masks for V197 }
  139. Const
  140.    V98 =  64;
  141.    V97   = 128;
  142.  
  143. { paramaters for V142 }
  144. Const
  145. { V137 }
  146.    V120 = 1;
  147.    V122  = 2;
  148.    V131 = 3;
  149. { V138 }
  150.    V162 = 1;
  151.    V149 = 2;
  152.    V146 = 3;
  153.    V148 = 4;
  154.    V183 = 5;
  155.    ZMDIfF = 6;
  156.    V163 = 7;
  157. { V139 }
  158.    V202 = 1;
  159.    V200 = 2;
  160.    V203 = 3;
  161. { V140 }
  162.    V118 = 1;
  163.  
  164. Var
  165.    { global variables }
  166.    V71 : Integer;
  167.    V4   : BufType;
  168.    V85    : BufType;
  169.    V107     : hdrType;
  170.    V77     : hdrType;
  171.    V78     : LongInt;
  172.    V79 : Integer;
  173.    V80    : Integer;
  174.    V76 : Integer;
  175.    V39  : String;
  176.    V42  : LongInt;
  177.    V38 : LongInt;
  178.    V21 : Boolean;
  179.    V108     : LongInt;
  180.    V32: Word;
  181.    V92 : Boolean;
  182. Const
  183.    V59: Byte = 0;
  184.    V27   :  array[0..3] of char = 'EGQW';
  185.    V26 :  String = 'ZCRCX: Pos=';
  186.  
  187. Procedure V24;
  188. Begin
  189.    WriteMsg('Disk I/O Error')
  190. end;
  191.  
  192. Procedure V152(x:Char; n: Integer; V55:HdrType);
  193. Var
  194.    i      : Integer;
  195.    Text : String;
  196. Begin
  197.    If (n > 20) Then n := 20;
  198.    Text := x + ':';
  199.    CASE n OF
  200.      -42 : Text := Text + 'MESSED_UP';
  201.      -41 : Text := Text + 'ZNOCARRIER';
  202.      -40 : Text := Text + 'ZERROR';
  203.      -1  : Text := Text + 'ZTIMEOUT';
  204.    end;
  205.    if Debug then CASE n OF
  206.       0  : Text := Text + 'ZRQINIT';
  207.       1  : Text := Text + 'ZRINIT';
  208.       2  : Text := Text + 'ZSINIT';
  209.       3  : Text := Text + 'ZACK';
  210.       4  : Text := Text + 'ZFILE';
  211.       5  : Text := Text + 'ZSKIP';
  212.       6  : Text := Text + 'ZNAK';
  213.       7  : Text := Text + 'ZABORT';
  214.       8  : Text := Text + 'ZFIN';
  215.       9  : Text := Text + 'ZRPOS';
  216.       10 : Text := Text + 'ZDATA';
  217.       11 : Text := Text + 'ZEOF';
  218.       12 : Text := Text + 'ZFERR';
  219.       13 : Text := Text + 'ZCRC';
  220.       14 : Text := Text + 'ZCHALLENGE';
  221.       15 : Text := Text + 'ZCOMPL';
  222.       16 : Text := Text + 'ZCAN';
  223.       17 : Text := Text + 'ZFREECNT';
  224.       18 : Text := Text + 'ZCOMMAND';
  225.       19 : Text := Text + 'ZSTDERR';
  226.    Else
  227.       Text := Text + 'ZUNKNOWN';
  228.    End;
  229.    if Length(Text) > 2 then WriteMsg(Text);
  230. End;
  231.  
  232. Procedure V175(V99: Byte);
  233. var
  234.    i : Integer;
  235. Begin
  236.    {escape certain control chars}
  237.    If ((V99 AND $7F) IN [16,17,19,24]) OR (((V99 AND $7F) = 13)
  238.     AND ((V59 And $7F) = 64)) Then
  239.       Begin
  240.          i := SioPutc(V71,chr(V133));
  241.          V59 := (V99 XOR 64)
  242.       End
  243.    Else V59 := V99;
  244.    i := SioPutc(V71,chr(V59))
  245. End;
  246.  
  247. Function V151 : LongInt;
  248. Var
  249.    V37 : BufType;
  250.    V20     : LongInt;
  251.    n       : Integer;
  252.    V7   : Word;
  253. Begin
  254.    V20 := $FFFFFFFF;
  255.    If not fioSeek(0) Then {null};
  256.    Repeat
  257.       
  258.       if not fioRead(V37,V117,V7) then V24;
  259.       
  260.       For n := 0 To (V7 - 1) Do
  261.          V20 := UpdateCrc32(V37[n],V20)
  262.    Until (V7 < V117) OR (IOresult <> 0);
  263.    If not fioSeek(0) Then ;
  264.    V151 := V20
  265. End;
  266.  
  267. Function V147 : Boolean;
  268. Begin
  269.   {V147 := SioDCD(V71)}
  270.   V147 := True
  271. end;
  272.  
  273. Function V155(V103: Integer): Integer;
  274. { Returns V72 if no carrier, or }
  275. { V201 if nothing received }
  276. { within 'Tics' tics (18.2 tics per second.}
  277. Var
  278.    i : Integer;
  279. Begin
  280.    Repeat
  281.       If (NOT V147) Then
  282.       Begin
  283.          V155 := V72;
  284.          Exit
  285.       End;
  286.       i :=  SioGetc(V71,1);
  287.       If i >= 0 Then
  288.          Begin
  289.             V155 := i;
  290.             Exit
  291.          End;
  292.       Dec(V103)
  293.    Until (V103 <= 0);
  294.    { timed out }
  295.    V155 := V201
  296. End;
  297.  
  298. Function V166: Integer;
  299. { Strips parity & ignores V111/V110 characters. }
  300. Var
  301.    c: Integer;
  302. Begin
  303.    Repeat
  304.       c := V155(V79) And $FF7F   {strip parity }
  305.    Until (c < 0) OR (NOT (Lo(c) IN [17,19])); {wait for other than V111/V110 }
  306.    V166 := c
  307. End;
  308.  
  309. Procedure V176;
  310. { Send a zmodem cancel sequence }
  311. Var
  312.    i, n: BYTE;
  313. Begin
  314.    i := SioTxFlush(V71);
  315.    For n := 1 To 8 Do
  316.       Begin
  317.          i := SioPutc(V71,chr(V10));
  318.          SioDelay(V95)
  319.       End;
  320.    For n := 1 To 10 Do i := SioPutc(V71,chr(8));
  321. End;
  322.  
  323. Procedure zmPutString(Var p: BufType);
  324. { Outputs ASCIIZ string }
  325. Var
  326.    i, n: Integer;
  327. Begin
  328.    n := 0;
  329.    While (n < V117) And (p[n] <> 0) Do
  330.    Begin
  331.       CASE p[n] OF
  332.          221 : i := SioBrkSig(V71,ASSERT);
  333.          222 : SioDelay(V105)
  334.          Else i := SioPutc(V71,chr(p[n]))
  335.       End;
  336.       Inc(n)
  337.    End
  338. End;
  339.  
  340. Procedure zmPutHex(Byte: BYTE);
  341. Const
  342.    V56: ARRAY[0..15] OF CHAR = '0123456789abcdef';
  343. Var
  344.    i : Integer;
  345. Begin
  346.    i := SioPutc(V71,V56[Byte SHR 4]);
  347.    i := SioPutc(V71,V56[Byte And $0F])
  348. End;
  349.  
  350. Procedure V182(hType: BYTE; Var V55: hdrType);
  351. { Sends a hex header }
  352. Var
  353.    V20 : Word;
  354.    n, i: Integer;
  355. Begin
  356.    V152('S',hType,V55); {mdm}
  357.    i := SioPutc(V71,chr(V191));
  358.    i := SioPutc(V71,chr(V191));
  359.    i := SioPutc(V71,chr(V133));
  360.    i := SioPutc(V71,chr(V145));
  361.    zmPutHex(hType);
  362.    V20 := UpdateCrc16(hType,0);
  363.    For n := 0 To 3 Do
  364.       Begin
  365.          zmPutHex(V55[n]);
  366.          V20 := UpdateCrc16(V55[n],V20)
  367.       End;
  368.    V20 := UpdateCrc16(0,V20);
  369.    V20 := UpdateCrc16(0,V20);
  370.    zmPutHex(Lo(V20 SHR 8));
  371.    zmPutHex(Lo(V20));
  372.    i := SioPutc(V71,chr(13));
  373.    i := SioPutc(V71,chr(10));
  374.    If (hType <> V143) And (hType <> V113) Then
  375.       i := SioPutc(V71,chr(17));  {XON}
  376.    If (NOT V147) Then
  377.       i := SioTxFlush(V71);
  378. End;
  379.  
  380. Function V159(Var V55: hdrType): LongInt;
  381. Var
  382.    V60: LongInt;
  383. Begin
  384.    V60 := V55[V190];
  385.    V60 := (V60 SHL 8) OR V55[V189];
  386.    V60 := (V60 SHL 8) OR V55[V188];
  387.    V60 := (V60 SHL 8) OR V55[V187];
  388.    V159 := V60
  389. End;
  390.  
  391. Procedure V165(V60: LongInt);
  392. Begin
  393.    V107[V187] := BYTE(V60);
  394.    V107[V188] := BYTE(V60 SHR 8);
  395.    V107[V189] := BYTE(V60 SHR 16);
  396.    V107[V190] := BYTE(V60 SHR 24)
  397. End;
  398.  
  399. Function V161: Integer;
  400. { Gets a byte by ZMODEM escape coding }
  401. Var
  402.    c, d: Integer;
  403. Begin
  404.    If (NOT V147) Then
  405.    Begin
  406.       V161 := V72;
  407.       Exit
  408.    End;
  409.    c := V155(V79);
  410.    If (c <> V133) Then
  411.    Begin
  412.       V161 := c;
  413.       Exit
  414.    End;
  415.    {got V133 or 1st CAN}
  416.    c := V155(V79);
  417.    If (c = V10) Then
  418.    Begin
  419.       {got 2nd CAN}
  420.       c := V155(V79);
  421.       If (c = V10) Then
  422.       Begin
  423.          {got 3rd CAN}
  424.          c := V155(V79);
  425.          If (c = V10) Then
  426.             {got 4th CAN}
  427.             c := V155(V79);
  428.       End
  429.    End;
  430.    { Flags set in high byte }
  431.    CASE c OF
  432.       V10: V161 := V48; {got 5th CAN}
  433.       V127, V128, V129, V130:
  434.          Begin
  435.            {got a frame end marker}
  436.            V161 := (c OR V53)
  437.          End;
  438.       V195:
  439.          V161 := $007F; {ASCII DEL}
  440.       V196:
  441.          V161 := $00FF  {any parity}
  442.     Else
  443.       Begin
  444.          If (c < 0) Then V161 := c
  445.          Else If ((c And $60) = $40) Then
  446.             V161 := c XOR $40
  447.          Else
  448.             V161 := V136
  449.       End
  450.    End
  451. End;
  452.  
  453. Function V157: Integer;
  454. { Get a byte received as two ASCII hex digits }
  455. Var
  456.    c, n: Integer;
  457. Begin
  458.    n := V166;
  459.    If (n < 0) Then
  460.       Begin
  461.          V157 := n;
  462.          Exit
  463.       End;
  464.    n := n - $30;
  465.    If (n > 9) Then n := n - 39;
  466.    If (n And $FFF0 <> 0) Then
  467.       Begin
  468.          V157 := V136;
  469.          Exit
  470.       End;
  471.    c := V166;
  472.    If (c < 0) Then
  473.       Begin
  474.          V157 := c;
  475.          Exit
  476.       End;
  477.    c := c - $30;
  478.    If (c > 9) Then c := c - 39;
  479.    If (c And $FFF0 <> 0) Then
  480.       Begin
  481.          V157 := V136;
  482.          Exit
  483.       End;
  484.    V157 := (n SHL 4) OR c
  485. End;
  486.  
  487. Function V158(Var V55: hdrType): Integer;
  488. { Receives a hex header }
  489. Var
  490.    V20 : Word;
  491.    c, n: Integer;
  492. Begin
  493.    c := V157;
  494.    If (c < 0) Then
  495.       Begin
  496.          V158 := c;
  497.          Exit
  498.       End;
  499.    V80 := c;
  500.    V20 := UpdateCrc16(V80,0);
  501.    For n := 0 To 3 Do
  502.       Begin
  503.          c := V157;
  504.          If (c < 0) Then
  505.             Begin
  506.                V158 := c;
  507.                Exit
  508.             End;
  509.          V55[n] := Lo(c);
  510.          V20 := UpdateCrc16(Lo(c),V20)
  511.       End;
  512.    c := V157;
  513.    If (c < 0) Then
  514.       Begin
  515.          V158 := c;
  516.          Exit
  517.       End;
  518.    V20 := UpdateCrc16(Lo(c),V20);
  519.    c := V157;
  520.    If (c < 0) Then
  521.       Begin
  522.          V158 := c;
  523.         Exit
  524.       End;
  525.    V20 := UpdateCrc16(Lo(c),V20);
  526.    If (V20 <> 0) Then
  527.       Begin
  528.          {write('[CRC error]');}{mdm}
  529.          Inc(V32);
  530.          WriteIntMsg('Error(1)=',V32);
  531.          V158 := V136;
  532.          Exit
  533.       End;
  534.    If (V155(1) = 13) Then c := V155(1);
  535.    V158 := V80
  536. End;
  537.  
  538.  
  539. Function V153(Var V55: hdrType): Integer;
  540. { Receives a binary header with 16 bit CRC }
  541. Var
  542.    V20 : Word;
  543.    c, n: Integer;
  544. Begin
  545.    c := V161;
  546.    If (c < 0) Then
  547.    Begin
  548.       V153 := c;
  549.       Exit
  550.    End;
  551.    V80 := c;
  552.    V20 := UpdateCrc16(V80,0);
  553.    For n := 0 To 3 Do
  554.       Begin
  555.          c := V161;
  556.          If (Hi(c) <> 0) Then
  557.             Begin
  558.                V153 := c;
  559.                Exit
  560.             End;
  561.          V55[n] := Lo(c);
  562.          V20 := UpdateCrc16(Lo(c),V20)
  563.       End;
  564.    c := V161;
  565.    If (Hi(c) <> 0) Then
  566.       Begin
  567.          V153 := c;
  568.          Exit
  569.       End;
  570.    V20 := UpdateCrc16(Lo(c),V20);
  571.    c := V161;
  572.    If (Hi(c) <> 0) Then
  573.       Begin
  574.          V153 := c;
  575.          Exit
  576.       End;
  577.    V20 := UpdateCrc16(Lo(c),V20);
  578.    If (V20 <> 0) Then
  579.       Begin
  580.          Inc(V32);
  581.          WriteIntMsg('Error(2)=',V32);
  582.          Exit
  583.       End;
  584.    V153 := V80
  585. End;
  586.  
  587.  
  588. Function V154(Var V55: hdrType): Integer;
  589. { Receives a binary header with 32 bit CRC }
  590. Var
  591.    V20 : LongInt;
  592.    c, n: Integer;
  593. Begin
  594.    c := V161;
  595.    If (c < 0) Then
  596.    Begin
  597.       V154 := c;
  598.       Exit
  599.    End;
  600.    V80 := c;
  601.    V20 := UpdateCrc32(V80,$FFFFFFFF);
  602.    For n := 0 To 3 Do
  603.    Begin
  604.       c := V161;
  605.       If (Hi(c) <> 0) Then
  606.       Begin
  607.          V154 := c;
  608.          Exit
  609.       End;
  610.       V55[n] := Lo(c);
  611.       V20 := UpdateCrc32(Lo(c),V20)
  612.    End;
  613.    For n := 0 To 3 Do
  614.    Begin
  615.       c := V161;
  616.       If (Hi(c) <> 0) Then
  617.       Begin
  618.          V154 := c;
  619.          Exit
  620.       End;
  621.       V20 := UpdateCrc32(Lo(c),V20)
  622.    End;
  623.    If (V20 <> $DEBB20E3) Then
  624.    Begin
  625.       Inc(V32);
  626.       WriteIntMsg('Error(3)=',V32);
  627.       V154 := V136;
  628.       Exit
  629.    End;
  630.    V154 := V80
  631. End;
  632.  
  633. Function V156(Var V55: hdrType): Integer;
  634. Label
  635.    V47, V2, again2, V89, V25;
  636. Var
  637.    i, c, n : Integer;
  638.    V12: Integer;
  639. Begin
  640.    n := 32;
  641.    V12 := 5;
  642.    V21 := FALSE;
  643. V2:
  644.    If (KeyPressed) Then
  645.       If (ReadKey = chr(V10)) Then
  646.       Begin
  647.          V176;
  648.          WriteMsg('Cancelled by USER');
  649.          V156 := V119;
  650.          Exit
  651.       End;
  652.    V76 := 0;
  653.    V80 := 0;
  654.    {expect to read ZPAD}
  655.    c := V166;
  656.    CASE c OF
  657.       V191:
  658.          ;
  659.       V72, V201:
  660.          goto V25;
  661.       V10:
  662.          Begin
  663. V47:
  664.            Dec(V12);
  665.            If (V12 < 0) Then
  666.            Begin
  667.               c := V119;
  668.               goto V25
  669.            End;
  670.            c := V155(1);
  671.            CASE c OF
  672.               V201:
  673.                  goto V2;
  674.               V130:
  675.                  Begin
  676.                     c := V136;
  677.                     goto V25
  678.                  End;
  679.               V72:
  680.                  goto V25;
  681.               V10:
  682.                  Begin
  683.                     Dec(V12);
  684.                     If (V12 < 0) Then
  685.                     Begin
  686.                        c := V119;
  687.                        goto V25
  688.                     End;
  689.                     goto V2
  690.                  End
  691.               Else
  692.                 {fallthru}
  693.            End {case}
  694.          End {can}
  695.    Else {case}
  696.          {char is not V191 !}
  697. again2:    Begin
  698.             Dec(n);
  699.             If (n < 0) Then
  700.                Begin
  701.                   Inc(V32);
  702.                   WriteIntMsg('Header is unrecognizable. Errors=',V32);
  703.                   V156 := V136;
  704.                   Exit
  705.                End;
  706.             If (c <> V10) Then V12 := 5;
  707.             {go back to continue looking for ZPAD}
  708.             goto V2
  709.          End
  710.    End; {case}
  711.    {got ZPAD}
  712.    V12 := 5;
  713. V89:
  714.    c := V166;
  715.    CASE c OF
  716.       V133:
  717.          {this is what we want!} ;
  718.       V191:
  719.          goto V89;   {junk or second '*' of a hex header}
  720.       V72, V201:
  721.          goto V25
  722.       Else
  723.          goto again2
  724.    End; {case}
  725.    {got ZDLE}
  726.    c := V166;
  727.    CASE c OF
  728.       V116:
  729.          Begin
  730.             V76 := V116;
  731.             c := V154(V55);
  732.          End;
  733.       V115:
  734.          Begin
  735.             V76 := V115;
  736.             c := V153(V55);
  737.          End;
  738.       V145:
  739.          Begin
  740.             V76 := V145;
  741.             c := V158(V55);
  742.          End;
  743.       V10:
  744.          goto V47;
  745.       V72, V201:
  746.          goto V25
  747.       Else
  748.          goto again2
  749.    End; {only falls thru if we got V115, V116 or ZHEX}
  750.    V78 := V159(V55);
  751. V25:
  752.    V152('R',c,V55); {mdm}
  753.    V156 := c
  754. End;
  755. {*******************}
  756. { RECEIVE  ROUTINES }
  757. {*******************}
  758.  
  759. Var
  760.    {zmBatch : Boolean;}  {mdm}
  761.    TryZhdrType: BYTE;
  762.    V75  : Integer;
  763.    V41: LongInt;
  764.    V57 : Boolean;
  765.    V29  : Boolean;
  766.    V125    : BYTE;
  767.  
  768. Function V167(Var V8: BufType; V5: Integer): Integer;
  769. { Get a 32 bit CRC data block }
  770. Label
  771.    V22;
  772. Var
  773.    c, d: Integer;
  774.    n, i: Integer;
  775.    V20 : LongInt;
  776.    V25: Boolean;
  777. Begin
  778.    V21 := TRUE;
  779.    V20 := $FFFFFFFF;
  780.    V75 := 0;
  781.    V25 := FALSE;
  782.    Repeat
  783.       c := V161;
  784.       If (Hi(c) <> 0) Then
  785.       Begin
  786. V22:
  787.          CASE c OF
  788.             V49,V50,V51,V52:
  789.                Begin
  790.                   d := c;
  791.                   V20 := UpdateCrc32(Lo(c),V20);
  792.                   For n := 0 To 3 Do
  793.                   Begin
  794.                      c := V161;
  795.                      If (Hi(c) <> 0) Then goto V22;
  796.                      V20 := UpdateCrc32(Lo(c),V20)
  797.                   End;
  798.                   If (V20 <> $DEBB20E3) Then
  799.                      Begin
  800.                         Inc(V32);
  801.                         WriteIntMsg('Error(4)=',V32);
  802.                         V167 := V136
  803.                      End
  804.                   Else
  805.                      V167 := d;
  806.                   V25 := TRUE
  807.                End;
  808.             V48:
  809.                Begin
  810.                   V167 := V119;
  811.                   V25 := TRUE
  812.                End;
  813.             V201:
  814.                Begin
  815.                   V167 := c;
  816.                   V25 := TRUE
  817.                End;
  818.             V72:
  819.                Begin
  820.                   V167 := c;
  821.                   V25 := TRUE
  822.                End
  823.             Else
  824.                Begin
  825.                   WriteMsg('Garbage...');
  826.                   i := SioRxFlush(V71);
  827.                   V167 := c;
  828.                   V25 := TRUE
  829.                End
  830.          End {case}
  831.       End;
  832.       If (NOT V25) Then
  833.       Begin
  834.          Dec(V5);
  835.          If (V5 < 0) Then
  836.          Begin
  837.             WriteMsg('Long packet');
  838.             V167 := V136;
  839.             V25 := TRUE
  840.          End;
  841.          V8[Integer(V75)] := Lo(c);
  842.          Inc(V75);
  843.          V20 := UpdateCrc32(Lo(c),V20)
  844.       End
  845.    Until V25
  846. End;
  847.  
  848. Function V170(Var V8: BufType; V5: Integer): Integer;
  849. { get a 16 bit CRC data block }
  850. Label
  851.    V22;
  852. Var
  853.    i, c, d: Integer;
  854.    V20 : Word;
  855.    V25: Boolean;
  856. Begin
  857.    If (V76 = V116) Then
  858.       Begin
  859.          {WriteLn('CRC32');}
  860.          V170 := V167(V8,V5);
  861.          Exit
  862.       End;
  863.    {WriteLn('CRC16');}
  864.    V20 := 0;
  865.    V75 := 0;
  866.    V25 := FALSE;
  867.    Repeat
  868.       c := V161;
  869.       If (Hi(c) <> 0) Then
  870.       Begin
  871. V22:  CASE c OF
  872.             V49,V50,V51,V52:
  873.                Begin
  874.                   d := c;
  875.                   V20 := UpdateCrc16(Lo(c),V20);
  876.                   c := V161;
  877.                   If (Hi(c) <> 0) Then goto V22;
  878.                   V20 := UpdateCrc16(Lo(c),V20);
  879.                   c := V161;
  880.                   If (Hi(c) <> 0) Then goto V22;
  881.                   V20 := UpdateCrc16(Lo(c),V20);
  882.                   If (V20 <> 0) Then
  883.                      Begin
  884.                         Inc(V32);
  885.                         WriteIntMsg('Error(5)=',V32);
  886.                         V170 := V136;
  887.                         V25 := TRUE
  888.                      End;
  889.                   V170 := d;
  890.                   V25 := TRUE
  891.                End;
  892.             V48:
  893.                Begin
  894.                   WriteMsg('Received CAN');
  895.                   V170 := V119;
  896.                   V25 := TRUE
  897.                End;
  898.             V201:
  899.                Begin
  900.                   V170 := c;
  901.                   V25 := TRUE
  902.                End;
  903.             V72:
  904.                Begin
  905.                   WriteMsg('Lost carrier');
  906.                   V170 := c;
  907.                   V25 := TRUE
  908.                End
  909.             Else
  910.                Begin
  911.                   WriteMsg('Garbage...');
  912.                   i := SioRxFlush(V71);
  913.                   V170 := c;
  914.                   V25 := TRUE
  915.                End
  916.          End {case}
  917.       End;
  918.       If (NOT V25) Then
  919.       Begin
  920.          Dec(V5);
  921.          If (V5 < 0) Then
  922.          Begin
  923.             WriteMsg('Long packet');
  924.             V170 := V136;
  925.             V25 := TRUE
  926.          End;
  927.          V8[Integer(V75)] := Lo(c);
  928.          Inc(V75);
  929.          V20 := UpdateCrc16(Lo(c),V20)
  930.       End
  931.    Until V25
  932. End;
  933.  
  934. Procedure V81;
  935. { Acknowledge request to terminate cleanly }
  936. Var
  937.    n, i: Integer;
  938. Begin
  939.    V165(V78);
  940.    n := 4;
  941.    i := SioRxFlush(V71);
  942.    Repeat
  943.       V182(V143,V107);
  944.       CASE V155(V105) OF
  945.          V201, V72:
  946.             Exit;
  947.          79:
  948.             Begin
  949.                 If V155(ONE_SECOND) = 79 Then
  950.                    {null};
  951.                 i := SioRxFlush(V71);
  952.                 Exit
  953.             End
  954.          Else
  955.             i := SioRxFlush(V71);
  956.             Dec(n)
  957.       End {case}
  958.    Until (n <= 0)
  959. End;
  960.  
  961. Function V83: Integer;
  962. Label
  963.    V2;
  964. Var
  965.    c, n  : Integer;
  966.    V33: Integer;
  967.    V43  : Byte;
  968. Begin
  969.    FillChar(V4,V114,0);
  970.    V32 := 0;
  971.    V33 := 0;
  972.    For n := 10 DownTo 0 Do
  973.    Begin
  974.       If (NOT V147) Then
  975.       Begin
  976.          WriteMsg('Lost carrier');
  977.          V83 := V136;
  978.          Exit
  979.       End;
  980.       V165(LongInt(0));
  981.       V43 := V15 OR V17 OR V14 OR V11;
  982.       V107[V137] := V43;
  983.       V182(TryZhdrType,V107);
  984.       If (TryZhdrType = V198) Then TryZhdrType := V192;
  985. V2:
  986.       c := V156(V77);
  987.       CASE c OF
  988.          V142:
  989.             Begin
  990.                V125 := V77[V137];
  991.                TryZhdrType := V192;
  992.                c := V170(V85,V117);
  993.                If (c = V52) Then
  994.                   Begin
  995.                      V83 := V142;
  996.                      Exit
  997.                   End;
  998.                V182(V185,V107);
  999.                goto V2
  1000.             End;
  1001.          V197:
  1002.             Begin
  1003.                c := V170(V4,V117);
  1004.                If (c = V52)
  1005.                   Then V182(V113,V107)
  1006.                   Else V182(V185,V107);
  1007.                goto V2
  1008.             End;
  1009.          V144:
  1010.             Begin
  1011.                V165(DiskFree(0));
  1012.                V182(V113,V107);
  1013.                goto V2
  1014.             End;
  1015.          V123:
  1016.             Begin
  1017.                c := V170(V85,V117);
  1018.                If (c = V52) Then
  1019.                Begin
  1020.                   V165(LongInt(0));
  1021.                   Repeat
  1022.                      V182(V124,V107);
  1023.                      Inc(V33)
  1024.                   Until (V33 > 10) OR (V156(V77) = V143);
  1025.                   V81;
  1026.                   V83 := V124;
  1027.                   Exit
  1028.                End;
  1029.                V182(V185,V107);
  1030.                goto V2
  1031.             End;
  1032.          V124, V143:
  1033.             Begin
  1034.                V83 := V124;
  1035.                Exit
  1036.             End;
  1037.          V119, V72:
  1038.             Begin
  1039.                V83 := c;
  1040.                Exit
  1041.            End
  1042.       End {case}
  1043.    End; {for}
  1044.    WriteMsg('Timed out');
  1045.    V83 := V136
  1046. End;
  1047.  
  1048. Function V82: Integer;
  1049. Var
  1050.    e, p, n, i: Integer;
  1051.    V101 : String;
  1052.    V100   : LongInt;
  1053.    V23   : SearchRec;
  1054. Begin
  1055.    V57 := TRUE;
  1056.    V38 := LongInt(0);
  1057.    p := 0;
  1058.    V101 := '';
  1059.    While (p < 255) And (V85[p] <> 0) Do
  1060.    Begin
  1061.       V101 := V101 + UpCase(Chr(V85[p]));
  1062.       Inc(p)
  1063.    End;
  1064.    Inc(p);
  1065.    { get rid of drive & path specifiers }
  1066.    While (Pos(':',V101) > 0) Do Delete(V101,1,Pos(':',V101));
  1067.    While (Pos('\',V101) > 0) Do Delete(V101,1,Pos('\',V101));
  1068.    V39 := V101;
  1069.    { name completed }
  1070.    V38 := LongInt(0);
  1071.    While (p < V117) And (V85[p] <> $20) And (V85[p] <> 0) Do
  1072.    Begin
  1073.       V38 := (V38 *10) + Ord(V85[p]) - $30;
  1074.       Inc(p)
  1075.    End;
  1076.    Inc(p);
  1077.    { size completed }
  1078.    V101 := '';
  1079.    While (p < V117) And (V85[p] IN [$30..$37]) Do
  1080.       Begin
  1081.          V101 := V101 + Chr(V85[p]);
  1082.          Inc(p)
  1083.       End;
  1084.    Inc(p);
  1085.    V42 := Z2DosDate(V101);
  1086.    { time completed }
  1087.    {$I-}
  1088.    FindFirst(V39,Archive,V23);
  1089.    {$I+}
  1090.    If (DosError = 0) AND (IOresult = 0) Then
  1091.       Begin
  1092.          { file already exists }
  1093.          V100 := V23.Size;
  1094.          If (V125 = V131) And (V38 > V100) Then
  1095.             Begin
  1096.                V41 := V100;
  1097.                If not fioOpen(V39) Then
  1098.                   Begin
  1099.                      WriteMsg('Error opening '+V39);
  1100.                      V82 := V136;
  1101.                      Exit
  1102.                   End;
  1103.                If not fioSeek(V100) Then
  1104.                   Begin
  1105.                      WriteMsg('Error positioning file');
  1106.                      V82 := V136;
  1107.                      Exit
  1108.                   End;
  1109.                WriteMsg('Recovering')
  1110.             End
  1111.          Else
  1112.             Begin
  1113.                WriteMsg(V39+' is already complete');
  1114.                V82 := V198;
  1115.                Exit
  1116.             End
  1117.       End
  1118.    Else
  1119.       Begin
  1120.          V41 := 0;
  1121.          If not fioCreate(V39) Then
  1122.             Begin
  1123.                WriteMsg('Unable to create '+V39);
  1124.                V82 := V136;
  1125.                Exit
  1126.             End
  1127.       End;
  1128.    WriteLongMsg('Size=',V38);
  1129.    V82 := V186
  1130. End;
  1131.  
  1132. Function V84(Var V74: LongInt): Integer;
  1133. Begin
  1134.    If (KeyPressed) Then
  1135.       If (ReadKey = chr(V10)) Then
  1136.          Begin
  1137.             WriteMsg('Aborted by USER');
  1138.             V176;
  1139.             V84 := V136;
  1140.             Exit
  1141.          End;
  1142.    If not fioWrite(V85,V75) Then
  1143.       Begin
  1144.          V24;
  1145.          V84 := V136
  1146.       End
  1147.    Else V84 := V186;
  1148.    V74 := V74 + V75
  1149. End;
  1150.  
  1151. Function V171: Integer;
  1152. Label
  1153.    V31, V67, V62;
  1154. Var
  1155.    c, n   : Integer;
  1156.    V74: LongInt;
  1157.    V25   : Boolean;
  1158. Begin
  1159.    V32 := 0;
  1160.    V25 := FALSE;
  1161.    V29 := FALSE;
  1162.    c := V82;
  1163.    If (c <> V186) Then
  1164.    Begin
  1165.       If (c = V198) Then TryZhdrType := V198;
  1166.       V171 := c;
  1167.       Exit
  1168.    End;
  1169.    c := V186;
  1170.    n := 10;
  1171.    V74 := V41;
  1172.    V78 := V41;
  1173.    Repeat
  1174.       V165(V74);
  1175.       V182(V193,V107);
  1176. V67:
  1177.       c := V156(V77);
  1178.       CASE c OF
  1179.          V132:
  1180.             Begin
  1181.                If (V78 <> V74) Then
  1182.                   Begin
  1183.                       Dec(n);
  1184.                       Inc(V32);
  1185.                       WriteIntMsg('Error(6)=',V32);
  1186.                       If (n < 0) Then goto V31;
  1187.                       WriteMsg('Bad position');
  1188.                       zmPutString(V4)
  1189.                   End
  1190.                Else
  1191.                   Begin
  1192. V62:
  1193.                       c := V170(V85,V117);
  1194.                       CASE c OF
  1195.                          V119, V72:
  1196.                             goto V31;
  1197.                          V136:
  1198.                             Begin
  1199.                                Dec(n);
  1200.                                Inc(V32);
  1201.                                WriteIntMsg('Error',V32);
  1202.                                If (n < 0) Then goto V31;
  1203.                                zmPutString(V4)
  1204.                             End;
  1205.                          V201:
  1206.                             Begin
  1207.                                 Dec(n);
  1208.                                 If (n < 0) Then goto V31
  1209.                             End;
  1210.                          V52:
  1211.                             Begin
  1212.                                  n := 10;
  1213.                                  c := V84(V74);
  1214.                                  If (c <> V186) Then
  1215.                                     Begin
  1216.                                        V171 := c;
  1217.                                        Exit
  1218.                                     End;
  1219.                                  WriteLongMsg('ZCRCW: Pos=',V74);
  1220.                                  V165(V74);
  1221.                                  V182(V113,V107);
  1222.                                  goto V67
  1223.                              End;
  1224.                           V51:
  1225.                              Begin
  1226.                                 n := 10;
  1227.                                 c := V84(V74);
  1228.                                 If (c <> V186) Then
  1229.                                    Begin
  1230.                                       V171 := c;
  1231.                                       Exit
  1232.                                     End;
  1233.                                 WriteLongMsg('ZCRCQ: Pos=',V74);
  1234.                                 V165(V74);
  1235.                                 V182(V113,V107);
  1236.                                 goto V62
  1237.                              End;
  1238.                           V50:
  1239.                              Begin
  1240.                                 n := 10;
  1241.                                 c := V84(V74);
  1242.                                 If (c <> V186) Then
  1243.                                    Begin
  1244.                                       V171 := c;
  1245.                                       Exit
  1246.                                    End;
  1247.                                 WriteLongMsg('ZCRCG: Pos=',V74);
  1248.                                 goto V62
  1249.                              End;
  1250.                          V49:
  1251.                              Begin
  1252.                                 n := 10;
  1253.                                 c := V84(V74);
  1254.                                 If (c <> V186) Then
  1255.                                    Begin
  1256.                                       V171 := c;
  1257.                                       Exit
  1258.                                    End;
  1259.                                 WriteLongMsg('ZCRCE: Pos=',V74);
  1260.                                 goto V67
  1261.                              End
  1262.                       End {case}
  1263.                    End
  1264.                 End; {case of ZDATA}
  1265.          V185, V201:
  1266.             Begin
  1267.                Dec(n);
  1268.                If (n < 0) Then goto V31;
  1269.                WriteLongMsg('Pos=',V74)
  1270.             End;
  1271.          V142:
  1272.             Begin
  1273.                c := V170(V85,V117);
  1274.             End;
  1275.          V135:
  1276.             If (V78 = V74) Then
  1277.                Begin
  1278.                   V171 := c;
  1279.                   Exit
  1280.                End
  1281.             Else goto V67;
  1282.          V136:
  1283.             Begin
  1284.                Dec(n);
  1285.                If (n < 0) Then goto V31;
  1286.                WriteLongMsg('Pos=',V74);
  1287.                zmPutSTring(V4)
  1288.             End
  1289.       Else {case}
  1290.          Begin
  1291.             c := V136;
  1292.             goto V31
  1293.          End
  1294.       End {case}
  1295.    Until (NOT V25);
  1296. V31:
  1297.    V171 := V136
  1298. End;
  1299.  
  1300. Function V169: Integer;
  1301. Var
  1302.    c    : Integer;
  1303.    V103 : LongInt;
  1304. Begin
  1305.    WriteMsg('Receiving');
  1306.    While (True) Do
  1307.       Begin
  1308.          If NOT (V147) Then
  1309.             Begin
  1310.             V169 := V136;
  1311.             Exit
  1312.          End;
  1313.          V103 := SioTimer;
  1314.          c := V171;
  1315.          fioSetFTime(V42);
  1316.          WriteCPS(V103,V38,V39,(c=V198));
  1317.          fioClose;
  1318.          CASE c OF
  1319.             V135,V198:
  1320.                Begin
  1321.                   c := V83;
  1322.                   CASE c OF
  1323.                      V142:
  1324.                         {null};
  1325.                      V124:
  1326.                         Begin
  1327.                            V81;
  1328.                            V169 := V186;
  1329.                            Exit
  1330.                         End;
  1331.                   Else {case}
  1332.                      Begin
  1333.                         V169 := V136;
  1334.                         Exit
  1335.                      End
  1336.                   End {case}
  1337.             End {begin}
  1338.          Else {case}
  1339.             Begin
  1340.                V169 := c;
  1341.                Exit
  1342.             End
  1343.          End {case}
  1344.       End {while}
  1345. End;
  1346.  
  1347.  
  1348. Function V168(V70: Integer): Boolean;
  1349. Var
  1350.    i: Integer;
  1351. Begin
  1352.    V71 := V70;
  1353.    WriteIntMsg('zmReceive: V71=',V71);
  1354.    V79 := V96;
  1355.    TryZhdrType := V192;
  1356.    i := V83;
  1357.    If (i = V124) OR ((i = V142) And ((V169) = V186)) Then
  1358.       Begin
  1359.          WriteMsg('Done.');
  1360.          V168 := TRUE
  1361.       End
  1362.    Else
  1363.       Begin
  1364.          i := SioTxFlush(V71);
  1365.          WriteMsg('Sending CAN');
  1366.          V176;
  1367.          WriteMsg('Done.');
  1368.          V168 := FALSE;
  1369.       End
  1370. End;
  1371.  
  1372. { Send ROUTINES }
  1373.  
  1374. Var
  1375.    V90   : LongInt;
  1376.    V106   : BufType;
  1377.    V73: Integer;
  1378.    {BlocksRead: Integer;}
  1379.  
  1380. Procedure V173(hType: BYTE; Var V55: hdrType);
  1381. Var
  1382.    V20 : LongInt;
  1383.    i, n: Integer;
  1384. Begin
  1385.    V152('S',hType,V55); {mdm}
  1386.    i := SioPutc(V71,chr(V191));
  1387.    i := SioPutc(V71,chr(V133));
  1388.    i := SioPutc(V71,chr(V116));
  1389.    V175(hType);
  1390.    V20 := UpdateCrc32(hType,$FFFFFFFF);
  1391.    For n := 0 To 3 Do
  1392.       Begin
  1393.          V175(V55[n]);
  1394.          V20 := UpdateCrc32(V55[n],V20)
  1395.       End;
  1396.    V20 := (NOT V20);
  1397.    For n := 0 To 3 Do
  1398.       Begin
  1399.          V175(BYTE(V20));
  1400.          V20 := (V20 SHR 8)
  1401.       End;
  1402.    If (hType <> V132) Then SioDelay(V95)
  1403. End;
  1404.  
  1405. Procedure V174(hType: BYTE; Var V55: hdrType);
  1406. Var
  1407.    V20 : Word;
  1408.    i, n: Integer;
  1409. Begin
  1410.    If (V21) Then
  1411.       Begin
  1412.          V173(hType,V55);
  1413.          Exit
  1414.       End;
  1415.    V152('S',hType,V55); {mdm}
  1416.    i := SioPutc(V71,chr(V191));
  1417.    i := SioPutc(V71,chr(V133));
  1418.    i := SioPutc(V71,chr(V115));
  1419.    V175(hType);
  1420.    V20 := UpdateCrc16(hType,0);
  1421.    For n := 0 To 3 Do
  1422.       Begin
  1423.          V175(V55[n]);
  1424.          V20 := UpdateCrc16(V55[n],V20)
  1425.       End;
  1426.    V20 := UpdateCrc16(0,V20);
  1427.    V20 := UpdateCrc16(0,V20);
  1428.    V175(Lo(V20 SHR 8));
  1429.    V175(Lo(V20));
  1430.    If (hType <> V132) Then SioDelay(V95)
  1431. End;
  1432.  
  1433. Procedure V177(Var V8: BufType; V5: Integer; V44: BYTE);
  1434. Var
  1435.    V20 : LongInt;
  1436.    i   : Integer;
  1437. Begin
  1438.    {send the data}
  1439.    V20 := $FFFFFFFF;
  1440.    For i := 0 To (V5 - 1) Do
  1441.       Begin
  1442.          V175(V8[i]);
  1443.          V20 := UpdateCrc32(V8[i],V20)
  1444.       End;
  1445.    {send Frame End & CRC}
  1446.    V20 := UpdateCrc32(V44,V20);
  1447.    V20 := (NOT V20);
  1448.    i := SioPutc(V71,chr(V133));
  1449.    i := SioPutc(V71,chr(V44));
  1450.    For i := 0 To 3 Do
  1451.       Begin
  1452.          V175(BYTE(V20));
  1453.          V20 := (V20 SHR 8)
  1454.       End;
  1455.    Begin
  1456.       i := SioPutc(V71,chr(17));
  1457.       {SioDelay(V95)}
  1458.    End
  1459. End;
  1460.  
  1461. Procedure V178(Var V8: BufType; V5: Integer; V44: BYTE);
  1462. Var
  1463.    V20 : Word;
  1464.    i, t: Integer;
  1465. Begin
  1466.    If (V21) Then
  1467.       Begin
  1468.          V177(V8,V5,V44);
  1469.          Exit
  1470.       End;
  1471.    {send the data}
  1472.    V20 := 0;
  1473.    For t := 0 To (V5 - 1) Do
  1474.       Begin
  1475.          V175(V8[t]);
  1476.          V20 := UpdateCrc16(V8[t],V20)
  1477.       End;
  1478.    {send Frame End & CRC}
  1479.    V20 := UpdateCrc16(V44,V20);
  1480.    i := SioPutc(V71,chr(V133));
  1481.    i := SioPutc(V71,chr(V44));
  1482.    V20 := UpdateCrc16(0,V20);
  1483.    V20 := UpdateCrc16(0,V20);
  1484.    V175(Lo(V20 SHR 8));
  1485.    V175(Lo(V20));
  1486.    If (V44 = V130) Then
  1487.       Begin
  1488.          i := SioPutc(V71,chr(17));
  1489.          {SioDelay(V95)}
  1490.       End
  1491. End;
  1492.  
  1493. Procedure V179;
  1494. Var
  1495.    i   : Integer;
  1496.    V25: Boolean;
  1497. Begin
  1498.    V25 := FALSE;
  1499.    Repeat
  1500.       V165(V108);
  1501.       V174(V143,V107);
  1502.       CASE V156(V77) OF
  1503.          V143:
  1504.             Begin
  1505.                i := SioPutc(V71,'O');
  1506.                i := SioPutc(V71,'O');
  1507.                SioDelay(V54);
  1508.                i := SioTxFlush(V71);
  1509.                Exit
  1510.             End;
  1511.          V119, V72, V141, V201:
  1512.             Exit
  1513.       End {case}
  1514.    Until (V25)
  1515. End;
  1516.  
  1517. Function V160: Integer;
  1518. Var
  1519.    n, c: Integer;
  1520. Begin
  1521.    WriteMsg('Getting info.');
  1522.    For n := 1 To 10 Do
  1523.       Begin
  1524.          c := V156(V77);
  1525.          CASE c OF
  1526.             V121:
  1527.                Begin
  1528.                   V165(V78);
  1529.                   V182(V113,V107)
  1530.                End;
  1531.             V123:
  1532.                Begin
  1533.                   V165(LongInt(0));
  1534.                   V182(V194,V107)
  1535.                End;
  1536.             V192:
  1537.                Begin
  1538.                   V73 := (Word(V77[V188]) SHL 8) OR V77[V187];
  1539.                   V21 := ((V77[V137] And V14) <> 0);
  1540.                   {if V21 then WriteLn('CRC32') else WriteLn('CRC16');}
  1541.                   V160 := V186;
  1542.                   Exit
  1543.                End;
  1544.             V119,V72,V201:
  1545.                Begin
  1546.                   V160 := V136;
  1547.                   Exit
  1548.                End
  1549.       Else {case}
  1550.          If (c <> V194) OR (V77[V137] <> V123) Then
  1551.             V182(V185,V107)
  1552.       End {case}
  1553.    End; {for}
  1554.    V160 := V136
  1555. End;
  1556.  
  1557. Function V184: Integer;
  1558. Var
  1559.    i, c     : Integer;
  1560.    V64: Integer;
  1561. Begin
  1562.    V64 := 7;
  1563.    Repeat
  1564.       c := V156(V77);
  1565.       i := SioRxFlush(V71);
  1566.       CASE c OF
  1567.          V201:
  1568.             Begin
  1569.                Dec(V64);
  1570.                If (V64 < 0) Then
  1571.                   Begin
  1572.                      V184 := V136;
  1573.                      Exit
  1574.                   End
  1575.             End;
  1576.          V119, V112, V143, V72:
  1577.             Begin
  1578.                V184 := V136;
  1579.                Exit
  1580.             End;
  1581.          V193:
  1582.             Begin
  1583.                If not fioSeek(V78) Then
  1584.                   Begin
  1585.                      WriteMsg('File seek error');
  1586.                      V184 := V136;
  1587.                      Exit
  1588.                   End;
  1589.                WriteMsg('Repositioning...');
  1590.                WriteLongMsg('Pos=',V78);
  1591.                V108 := V78;
  1592.                V184 := c;
  1593.                Exit
  1594.             End;
  1595.          V198, V192, V113:
  1596.             Begin
  1597.                V184 := c;
  1598.                Exit
  1599.             End
  1600.       Else {case}
  1601.          Begin
  1602.             WriteMsg('Unspecified error!');
  1603.             V174(V185,V107)
  1604.          End
  1605.       End {case}
  1606.    Until (False)
  1607. End;
  1608.  
  1609.  
  1610. Function V181: Integer;
  1611. Label
  1612.    V109, V88, V69;
  1613. Var
  1614.    i, c       : Integer;
  1615.    V44   : Integer;
  1616.    V65   : Word;
  1617.    V6: Word;
  1618.    V9  : Word;
  1619.    V61: Word;
  1620.    V45 : Word;
  1621.    V46 : Word;
  1622. Begin
  1623.    WriteMsg('Sending file');
  1624.    V46 := 1;
  1625.    V61 := V117;
  1626.    V6 := V61;
  1627. V88:
  1628.    If SioRxQue(V71) = 0 Then
  1629.       Begin
  1630. V109:
  1631.          c := V184;
  1632.          CASE c OF
  1633.             V198:
  1634.                Begin
  1635.                   V181 := V198;
  1636.                   Exit
  1637.                End;
  1638.             V113:
  1639.                {null};
  1640.             V193:
  1641.                Begin
  1642.                   Inc(V32);
  1643.                   WriteIntMsg('Error(7)=',V32);
  1644.                   If ((V6 SHR 2) > 32) Then
  1645.                      V6 := (V6 SHR 2)
  1646.                   Else
  1647.                      V6 := 32;
  1648.                   V45 := 0;
  1649.                   V46 := (V46 SHL 1) OR 1
  1650.                End;
  1651.             V192:
  1652.                Begin
  1653.                   V181 := V186;
  1654.                   Exit
  1655.                End
  1656.          Else {case}
  1657.             Begin
  1658.                V181 := V136;
  1659.                Exit
  1660.             End
  1661.          End {case};
  1662.       While (SioRxQue(V71) > 0) Do
  1663.          Begin
  1664.             CASE (V155(1)) OF
  1665.                V10, V191:
  1666.                   goto V109;
  1667.                V72:
  1668.                   Begin
  1669.                      V181 := V136;
  1670.                      Exit
  1671.                   End
  1672.             End {case}
  1673.          End
  1674.    End; {if char avail}
  1675.    V65 := V73;
  1676.    V165(V108);
  1677.    V174(V132,V107);
  1678.    Repeat
  1679.       If (KeyPressed) Then
  1680.          If (ReadKey = chr(V10)) Then
  1681.             Begin
  1682.                WriteMsg('Aborted by USER');
  1683.                V176;
  1684.                goto V69
  1685.             End;
  1686.       If (NOT V147) Then goto V69;
  1687.       if not fioRead(V106,V6,V9) then
  1688.          Begin
  1689.             V24;
  1690.             V176;
  1691.             goto V69
  1692.          End;
  1693.       
  1694.       If (V9 < V6) Then V44 := V127
  1695.       Else
  1696.          If (V73 <> 0) And (V65 <= V9) Then
  1697.             Begin
  1698.                V65 := V65 - V9;
  1699.                V44 := V130;
  1700.             End
  1701.          Else
  1702.             Begin
  1703.                if V92 then V44 := V128
  1704.                else V44 := V130;
  1705.             End;
  1706.       
  1707.       V178(V106,V9,V44);
  1708.       V108 := V108 + V9;
  1709.       V26[5] := V27[V44-104];
  1710.       WriteLongMsg(V26,V108);
  1711.       Inc(V45);
  1712.       If (V6 < V61) And (V45 > V46) Then
  1713.          Begin
  1714.             If ((V6 SHL 1) < V61) Then
  1715.                V6 := (V6 SHL 1)
  1716.             Else
  1717.                V6 := V61;
  1718.             V45 := 0
  1719.          End;
  1720.       If V44 = V130 Then goto V109;
  1721.       While SioRxQue(V71) > 0 Do
  1722.          Begin
  1723.             CASE V155(1) OF
  1724.                V10, V191:
  1725.                   Begin
  1726.                      WriteMsg('Trouble?');
  1727.                      i := SioTxFlush(V71);
  1728.                      V178(V106,0,V127);
  1729.                      goto V109
  1730.                   End;
  1731.                V72:
  1732.                   Begin
  1733.                      V181 := V136;
  1734.                      Exit
  1735.                   End
  1736.             End {case}
  1737.          End {while}
  1738.    Until (V44 <> V128);
  1739.    Repeat
  1740.       V165(V108);
  1741.       WriteMsg('Sending EOF');
  1742.       V174(V135,V107);
  1743.   SioDelay(5); {!!!}
  1744.       c := V184;
  1745.       CASE c OF
  1746.          V113:
  1747.             {null};
  1748.          V193:
  1749.             goto V88;
  1750.          V192:
  1751.             Begin
  1752.                V181 := V186;
  1753.                Exit
  1754.             End;
  1755.          V198:
  1756.             Begin
  1757.                V181 := c;
  1758.                Exit
  1759.             End
  1760.       Else {case}
  1761. V69:    Begin
  1762.             V181 := V136;
  1763.             Exit
  1764.          End
  1765.       End {case}
  1766.    Until (c <> V113)
  1767. End;
  1768.  
  1769. Function V180: Integer;
  1770. Var
  1771.    c   : Integer;
  1772. Begin
  1773.    V32 := Word(0);
  1774.    Repeat
  1775.       If KeyPressed Then
  1776.          If (ReadKey = chr(V10)) Then
  1777.             Begin
  1778.                V176;
  1779.                WriteMsg('Aborted from keyboard');
  1780.                V180 := V136;
  1781.                Exit
  1782.             End;
  1783.       If (NOT V147) Then
  1784.          Begin
  1785.             WriteMsg('Lost carrier');
  1786.             V180 := V136;
  1787.             Exit
  1788.          End;
  1789.       FillChar(V107,4,0);
  1790.       V107[V137] := V131; {recover}
  1791.       V174(V142,V107);
  1792.       V178(V106,V117,V130);
  1793.       Repeat
  1794.          c := V156(V77);
  1795.          CASE c OF
  1796.             V119, V72, V201, V143, V112:
  1797.                Begin
  1798.                   V180 := V136;
  1799.                   Exit
  1800.                End;
  1801.             V192:
  1802.                {null - this will cause a loopback};
  1803.             V126:
  1804.                Begin
  1805.                   V165(V151);
  1806.                   V182(V126,V107)
  1807.                End;
  1808.             V198:
  1809.                Begin
  1810.                  V180 := c;
  1811.                  Exit
  1812.                End;
  1813.             V193:
  1814.                Begin
  1815.                  If not fioSeek(V78) Then
  1816.                      Begin
  1817.                         WriteMsg('File positioning error');
  1818.                         V182(V141,V107);
  1819.                         V180 := V136;
  1820.                         Exit
  1821.                      End;
  1822.                   WriteLongMsg('Setting start position =',V78);
  1823.                   V90 := V78;
  1824.                   V108 := V78;
  1825.                   V180 := V181;
  1826.                   Exit
  1827.                 End
  1828.          End {case}
  1829.       Until (c <> V192)
  1830.    Until (False)
  1831. End;
  1832.  
  1833. Function V172(V70: Integer; TheFile: String; LastFile: Boolean): Boolean;
  1834. Var
  1835.    i, n     : Integer;
  1836.    V101: String;
  1837.    V23  : SearchRec;
  1838.    V103     : LongInt;
  1839. Begin
  1840.    V32 := 0;
  1841.    V71 := V70;
  1842.    If (NOT V147) Then
  1843.       Begin
  1844.          WriteMsg('Lost carrier');
  1845.          SioDelay(V105);
  1846.          V172 := FALSE;
  1847.          Exit
  1848.       End;
  1849.    {$I-}
  1850.    FindFirst(TheFile,Archive,V23);
  1851.    {$I+}
  1852.    If (DosError <> 0) OR (IOresult <> 0) Then
  1853.       Begin
  1854.          WriteMsg('Unable to open '+TheFile);
  1855.          V179;
  1856.          V172 := FALSE;
  1857.          Exit
  1858.       End
  1859.    else
  1860.       Begin
  1861.          V39 := V23.Name;
  1862.          V38 := V23.Size;
  1863.          V42 := V23.Time;
  1864.       End;
  1865.    WriteLongMsg('Filesize=',V38);
  1866.    Str(V38,V101);
  1867.    V101 := (V39 + #0 + V101 + ' ');
  1868.    V101 := V101 + Dos2Zdate(V42);
  1869.    n := Length(V101);
  1870.    For n := 1 To Length(V101) Do
  1871.       Begin
  1872.          If (V101[n] IN ['A'..'Z']) Then
  1873.             V101[n] := Chr(Ord(V101[n]) + $20)
  1874.       End;
  1875.    FillChar(V106,V117,0);
  1876.    Move(V101[1],V106[0],Length(V101));
  1877.    V79 := V96;
  1878.    V4[0] := Ord('r');
  1879.    V4[1] := Ord('z');
  1880.    V4[3] := 13;
  1881.    V4[4] := 0;
  1882.    
  1883.    zmPutString(V4);
  1884.    FillChar(V4,V114,0);
  1885.    V165(LongInt(0));
  1886.    V182(V194,V107);
  1887.    If V160 = V136 Then
  1888.       Begin
  1889.          V172 := FALSE;
  1890.          Exit
  1891.       End;
  1892.    If not fioOpen(V39) Then
  1893.       Begin
  1894.          WriteMsg('Cannot open '+V39);
  1895.          V176;
  1896.          V172 := FALSE;
  1897.          Exit
  1898.       End;
  1899.    { send the file }
  1900.    V103 := SioTimer;
  1901.    n := V180;
  1902.    WriteCPS(V103,V38,V39,(n=V198));
  1903.    fioClose;
  1904.    If IOresult <> 0 Then {ignore result};
  1905.    If LastFile Then V179;
  1906.    V172 := TRUE
  1907.    End;
  1908.  
  1909. function ZmodemTx(
  1910.          V70     : Integer;      { COM port }
  1911.      Var V40 : String;       { File spec buffer }
  1912.          V91   : Boolean)      { Can do streaming ? }
  1913.        : Boolean;
  1914. var
  1915.   V23  : SearchRec;
  1916.   V102 : String;
  1917.   V66 : String;
  1918.   V58 : Boolean;
  1919. begin
  1920.   V92 := V91;
  1921.   ZmodemTx := False;
  1922.   V58 := False;
  1923.   { fetch filespec if not already specified }
  1924.   if not FetchName(V40) then exit;
  1925.   { find first filename }
  1926.   FindFirst(V40,AnyFile,V23);
  1927.   if DosError = 0 then V102 := V23.Name
  1928.   else begin
  1929.     WriteMsg('Cannot open '+V40);
  1930.     exit
  1931.   end;
  1932.   { send each file in turn }
  1933.   repeat
  1934.       FindNext(V23);
  1935.       if DosError = 0 then V66 := V23.Name
  1936.       else V58 := True;
  1937.       ZmodemTx := V172(V70,V102,V58);
  1938.       V102 := V66;
  1939.   until V58;
  1940.   WriteMsg('ZMODEM completed');
  1941. end; {ZmodemTx}
  1942.  
  1943. function ZmodemRx(
  1944.          V70     : Integer;      { COM port }
  1945.      Var V39 : String;       { filename buffer }
  1946.          V91   : Boolean)      { Can do streaming ? }
  1947.        : Boolean;
  1948. begin
  1949.   V92 := V91;
  1950.   ZmodemRx := V168(V70);
  1951.   WriteMsg('ZMODEM completed');
  1952. end; {ZmodemRx}
  1953.  
  1954.  
  1955. End. {ZMODEM}
  1956.